package com.jeesit.cloud.spot.web.api_controller.contract;

import com.jeesit.cloud.annotation.ModuleLog;
import com.jeesit.cloud.dto.*;
import com.jeesit.cloud.spot.business.impl.IContractBiz;
import com.jeesit.cloud.spot.service.*;
import com.jeesit.cloud.util.DecimalUtil;
import com.jeesit.cloud.verify.UserAuthDetail;
import com.jeesit.cloud.constants.LogConstant;
import com.jeesit.cloud.util.ExportExcel;
import com.jeesit.cloud.validate.UpdateAction;
import com.jeesit.cloud.validate.CreateAction;
import com.jeesit.cloud.validate.QueryAction;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.units.qual.C;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import com.jeesit.cloud.model.*;

import org.springframework.beans.factory.annotation.Autowired;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.Size;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 *   相关接口
 *　　
 *   @description Contract 接口
 *   ---------------------------------
 *   @author lss
 *   @date 2024-01-15
 */
@Slf4j
@RestController
@RequestMapping("/api/auth/v1/contract")
@Api(tags = {"采销合同"})
public class ContractController {

    @Autowired
    private IContractService contractService;
    @Autowired
    private IContractBiz contractBiz;
    @Autowired
    private IContractFinanceService contractFinanceService;
    @Autowired
    private IContractPendingOrderService contractPendingOrderService;
    @Autowired
    private IContractDetailService contractDetailService;
    @Autowired
    private IContractDetailRecordService contractDetailRecordService;
    @Autowired
    private IContractStorageService contractStorageService;
    @Autowired
    private IContractSchemaService contractSchemaService;
    @Autowired
    private IHedgingSchemeService hedgingSchemeService;
    @Autowired
    private IHedgingSchemeInstService hedgingSchemeInstService;
    @Autowired
    private IHedgeSchemeAccountService hedgeSchemeAccountService;

    /**
     * @description 获取分页列表
     * ---------------------------------
     * @author lss
     * @date 2024-01-15
     */
    @ApiOperation("获取分页列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "会话标识", dataType = "String", paramType = "header", required = true),
            @ApiImplicitParam(name = "pageNo", value = "页码", dataTypeClass = Integer.class , paramType = "query", required = true),
            @ApiImplicitParam(name = "pageSize", value = "每页行数，最少10条，最多100条", dataTypeClass = Integer.class , paramType = "query", required = true)
    })
    @PostMapping(value = "/contract_page")
    public JSONResult<Page<Contract>> getContractPage(Authentication authentication,@Validated(QueryAction.class)ContractDto dto) {
        User user = ((UserAuthDetail)authentication.getPrincipal()).getUser();
        Page<Contract> page=new Page<Contract>(dto.getPageNo(), dto.getPageSize());
        contractService.page(page,dto);
        for (Contract it : page.getRecords()) {
            it.init();
        }
        JSONResult<Page<Contract>> res = new JSONResult<>();
        res.setMessage("");
        res.setSuccess(true);
        res.setData(page);
        return res;
    }

/**
     * @description 获取列表
     * ---------------------------------
     * @author lss
     * @date 2024-01-15
     */
    @ApiOperation("获取列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "会话标识", dataType = "String", paramType = "header", required = true),
            @ApiImplicitParam(name = "size", value = "查询数量，最多查询1000条", dataTypeClass = Integer.class, paramType = "query", required = true)
    })
    @PostMapping(value = "/contract_list")
    public JSONResult<Contract> getContractList(Authentication authentication, @Validated(QueryAction.class)ContractDto dto) {
        User user = ((UserAuthDetail)authentication.getPrincipal()).getUser();
        List<Contract> list = contractService.list(dto.getSize(),dto);
        if(dto.getUuid()!=null) {
            for (Contract it : list) {
                it.init();
                ContractFinanceDto contractFinanceDto = new ContractFinanceDto();
                contractFinanceDto.setContractUuid(it.getUuid());
                List<ContractFinance> contractFinances = contractFinanceService.list(1, contractFinanceDto);
                if(contractFinances.size()>0) {
                    it.setContractFinance(contractFinances.get(0));
                }else {
                    it.setContractFinance(new ContractFinance());
                }
                ContractStorageDto contractStorageDto = new ContractStorageDto();
                contractStorageDto.setContractUuid(it.getUuid());
                List<ContractStorage> contractStorages = contractStorageService.list(1, contractStorageDto);
                if(contractStorages.size()>0) {
                    it.setContractStorage(contractStorages.get(0));
                }else {
                    it.setContractStorage(new ContractStorage());
                }
                ContractPendingOrderDto contractPendingOrderDto = new ContractPendingOrderDto();
                contractPendingOrderDto.setContractUuid(it.getUuid());
                List<ContractPendingOrder> contractPendingOrders = contractPendingOrderService.list(1, contractPendingOrderDto);
                if(contractPendingOrders.size()>0){
                    it.setContractPendingOrder(contractPendingOrders.get(0));
                }else {
                    it.setContractPendingOrder(new ContractPendingOrder());
                }
                ContractDetailDto contractDetailDto = new ContractDetailDto();
                contractDetailDto.setContractUuid(it.getUuid());
                List<ContractDetail> contractDetails = contractDetailService.list(0, contractDetailDto);
                for (ContractDetail its : contractDetails) {
                        ContractDetailRecordDto contractDetailRecordDto = new ContractDetailRecordDto();
                        //contractDetailRecordDto.setSourceContractUuid(it.getUuid());
                        if(it.getIsContract()){//销售合同查询采购关系
                            contractDetailRecordDto.setSaleDetailUuid(its.getUuid());
                        }else {//采购合同查询销售关系
                            contractDetailRecordDto.setPurchaseDetailUuid(its.getUuid());
                        }
                    List<ContractDetailRecord> contractDetailRecords = contractDetailRecordService.list(0, contractDetailRecordDto);
                        List<ContractDetail> contractDetailList = new ArrayList<>();//查询明细对应采销关系
                        for(ContractDetailRecord rec:contractDetailRecords){
                           ContractDetailDto contractDetailDto1 = new ContractDetailDto();
                            if(it.getIsContract()) {//销售合同查询采购关系
                                contractDetailDto1.setUuid(rec.getPurchaseDetailUuid());
                                List<ContractDetail> list1 = contractDetailService.list(1, contractDetailDto1);
                                ContractDetail contractDetail = list1.get(0);
                                contractDetail.setOperationWeight(rec.getWeight());
                                contractDetail.setIsContract(false);
                                //冻结了自己的金额，编辑时还回去，前端可以输入
                                if(contractDetail.getFrozenWeight()>rec.getWeight()) {
                                    contractDetail.setFrozenWeight(DecimalUtil.valueOf(contractDetail.getFrozenWeight()).subtract(rec.getWeight()).doubleValue());
                                }
                                contractDetailList.add(contractDetail);
                            }else {
                                contractDetailDto1.setUuid(rec.getSaleDetailUuid());
                                List<ContractDetail> list1 = contractDetailService.list(1, contractDetailDto1);
                                ContractDetail contractDetail = list1.get(0);
                                contractDetail.setOperationWeight(rec.getWeight());
                                if(contractDetail.getFrozenWeight()>rec.getWeight()) {
                                    contractDetail.setFrozenWeight(DecimalUtil.valueOf(contractDetail.getFrozenWeight()).subtract(rec.getWeight()).doubleValue());
                                }
                                contractDetail.setIsContract(true);
                                contractDetailList.add(contractDetail);
                            }
                        }
                    its.setIsContract(it.getIsContract());
                        its.setContractDetails(contractDetailList);
                }
                it.setContractDetails(contractDetails);
                //套保方案相关
                ContractSchemaDto contractSchemaDto = new ContractSchemaDto();
                contractSchemaDto.setContractUuid(it.getUuid());
                List<ContractSchema> contractSchemas = contractSchemaService.list(1, contractSchemaDto);
                if(contractSchemas.size()>0) {
                    HedgingScheme hedgingScheme = hedgingSchemeService.getById(contractSchemas.get(0).getSchemaUuid());//套保方案
                    HedgingSchemeInstDto hedgingSchemeInstDto = new HedgingSchemeInstDto();
                    hedgingSchemeInstDto.setSchemeUuid(hedgingScheme.getUuid());
                    List<HedgingSchemeInst> hedgingSchemeInsts = hedgingSchemeInstService.list(0, hedgingSchemeInstDto);//套保明细
                    hedgingScheme.setHedgingSchemeInstDtos(hedgingSchemeInsts);
                    HedgeSchemeAccountDto hedgeSchemeAccountDto = new HedgeSchemeAccountDto();
                    hedgeSchemeAccountDto.setSchemeUuid(hedgingScheme.getUuid());
                    List<HedgeSchemeAccount> hedgeSchemeAccounts = hedgeSchemeAccountService.list(0, hedgeSchemeAccountDto);
                    hedgingScheme.setHedgeSchemeAccounts(hedgeSchemeAccounts);
                    it.setHedgingScheme(hedgingScheme);
                }

            }
        }
        if(dto.getIsContractedQuantity()!=null&&dto.getIsContractedQuantity()){
            for(Contract it :list){
                sumWeight(it);//计算合同量
            }
        }
        JSONResult<Contract> res = new JSONResult<>();
        res.setMessage("");
        res.setSuccess(true);
        res.setDatas(list);
        return res;
    }


    /**
     * @description 导出列表
     * ---------------------------------
     * @author lss
     * @date 2024-01-15
     */
    @ApiOperation("导出列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "会话标识", dataType = "String", paramType = "header", required = true)
    })
    @PreAuthorize("hasAnyAuthority('Contract_Export','SUPER_ADMIN')")
    @PostMapping(value = "/contract_export")
    public void export(HttpServletResponse response,Authentication authentication, @Validated(QueryAction.class)ContractDto dto) {
        User user = ((UserAuthDetail)authentication.getPrincipal()).getUser();
        List<Contract> datas = contractService.list(0,dto);
        String[] header = new String[]{"","财年","采销合同 0采购 1销售","合同编号","外部合同编号","合同类型 0后结算 1固定价  2基差","买方简称","买方id","卖方简称","卖方id","签订日期","品类名称","品类id","合同模式 0正套 1平反套 2不套保"," 敞口类型 0合同敞口 1库存敞口 2无敞口","业务部门名称","业务部门id","业务员姓名","业务员id","合同重量","合同金额","创建时间","创建人姓名","创建人id","修改时间","修改人姓名","修改人id","审批状态 0未审批 1已审批 2已拒绝 3已撤销","审批时间","审批人姓名","审批人id","月内销售重量","是否完结","旧合同保留信息","",""};
        List<List<Object>> list = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        DecimalFormat df = new DecimalFormat("0.00");
        for(Contract it : datas){
            List<Object> data = new ArrayList<>();
            data.add(it.getUuid());
            data.add(it.getFiscalYear());
            data.add(it.getIsContract());
            data.add(it.getContractNumber());
            data.add(it.getContractNumberExternal());
            data.add(it.getContractType());
            data.add(it.getPurShortname());
            data.add(it.getPurUuid());
            data.add(it.getSellShortname());
            data.add(it.getSellUuid());
            data.add(Optional.ofNullable(it.getContractDate()).map(s->sdf.format(s)).orElse(""));
            data.add(it.getCatalogName());
            data.add(it.getCatalogUuid());
            data.add(it.getContractStatus());
            data.add(it.getOpenStatus());
            data.add(it.getBizOrgName());
            data.add(it.getBizOrgUuid());
            data.add(it.getSalesmanName());
            data.add(it.getSalesmanUuid());
            data.add(Optional.ofNullable(it.getWeight()).map(s->df.format(s)).orElse(""));
            data.add(Optional.ofNullable(it.getContractAmount()).map(s->df.format(s)).orElse(""));
            data.add(Optional.ofNullable(it.getAddTime()).map(s->sdf.format(s)).orElse(""));
            data.add(it.getAddUserName());
            data.add(it.getAddUserUuid());
            data.add(Optional.ofNullable(it.getModTime()).map(s->sdf.format(s)).orElse(""));
            data.add(it.getModUserName());
            data.add(it.getModUserUuid());
            data.add(it.getCheckStatus());
            data.add(Optional.ofNullable(it.getCheckTime()).map(s->sdf.format(s)).orElse(""));
            data.add(it.getCheckUserName());
            data.add(it.getCheckUserUuid());
            data.add(Optional.ofNullable(it.getMonthWeight()).map(s->df.format(s)).orElse(""));
            data.add(it.getIsCompleted());
            data.add(it.getIsOld());
            data.add(it.getDeleted());
            list.add(data);
        }
        ExportExcel excel = new ExportExcel();
        excel.setName("");
        excel.exportToExcel(response,header,list,0);
    }

    /**
     * @description 新建
     *
     * @author lss
     * @date 2024-01-15
     */
    @ApiOperation("新建")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "Authorization", value = "会话标识", dataType = "String", paramType = "header", required = true)
    })
    @PreAuthorize("hasAnyAuthority('PurchaseContract_Add','SaleContract_Add','SUPER_ADMIN')")
    @ModuleLog("Contract")
    @PostMapping("/contract_add")
    public JSONResult<Contract> saveNewEntity(HttpServletRequest request,Authentication authentication, @Validated(CreateAction.class) ContractDto entity){
        User user = ((UserAuthDetail)authentication.getPrincipal()).getUser();
        JSONResult<Contract> res= contractBiz.saveData(user,null,entity);
        if(res.isSuccess()){
            request.setAttribute(LogConstant.LOG_KEY,new LogInfo(user.getId(), "保存，数据ID:"+res.firstData().getUuid()));
        }
        return res;
    }

    /**
     * @description 更新
     *
     * @author lss
     * @date 2024-01-15
     */
    @ApiOperation("更新 ")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "Authorization", value = "会话标识", dataType = "String", paramType = "header", required = true)
    })
    @PreAuthorize("hasAnyAuthority('PurchaseContract_Modify','SaleContract_Modify','SUPER_ADMIN')")
    @ModuleLog("Contract")
    @PostMapping("/contract_edit")
    public JSONResult<Contract> saveEditEntity(HttpServletRequest request,Authentication authentication,@Validated(UpdateAction.class) ContractDto entity){
        User user = ((UserAuthDetail)authentication.getPrincipal()).getUser();
        JSONResult<Contract> res= contractBiz.saveData(user,entity.getUuid(),entity);
        if(res.isSuccess()){
            request.setAttribute(LogConstant.LOG_KEY,new LogInfo(user.getId(), "更新，数据ID:"+res.firstData().getUuid()));
        }
        return res;
    }

    private JSONResult<Contract> saveData(User user,Long id,ContractDto entity){
        JSONResult<Contract> res = new JSONResult<>();
        Contract it = new Contract();
        if(id==null){
            it.setDeleted(false);
        } else {
            it = contractService.getById(entity.getUuid());
        }
        it.setFiscalYear(entity.getFiscalYear());
        it.setIsContract(entity.getIsContract());
        it.setContractNumber(entity.getContractNumber());
        it.setContractNumberExternal(entity.getContractNumberExternal());
        it.setContractType(entity.getContractType());
        it.setPurShortname(entity.getPurShortname());
        it.setPurUuid(entity.getPurUuid());
        it.setSellShortname(entity.getSellShortname());
        it.setSellUuid(entity.getSellUuid());
        it.setContractDate(entity.getContractDate());
        it.setCatalogName(entity.getCatalogName());
        it.setCatalogUuid(entity.getCatalogUuid());
        it.setContractStatus(entity.getContractStatus());
        it.setOpenStatus(entity.getOpenStatus());
        it.setBizOrgName(entity.getBizOrgName());
        it.setBizOrgUuid(entity.getBizOrgUuid());
        it.setSalesmanName(entity.getSalesmanName());
        it.setSalesmanUuid(entity.getSalesmanUuid());
        it.setWeight(entity.getWeight());
        it.setContractAmount(entity.getContractAmount());
        it.setAddUserName(entity.getAddUserName());
        it.setAddUserUuid(entity.getAddUserUuid());
        it.setModUserName(entity.getModUserName());
        it.setModUserUuid(entity.getModUserUuid());
        it.setCheckStatus(entity.getCheckStatus());
        it.setCheckTime(entity.getCheckTime());
        it.setCheckUserName(entity.getCheckUserName());
        it.setCheckUserUuid(entity.getCheckUserUuid());
        it.setMonthWeight(entity.getMonthWeight());
        it.setIsCompleted(entity.getIsCompleted());
        it.setIsOld(entity.getIsOld());
        contractService.saveOrUpdate(it);
        res.setData(it);
        res.setSuccess(true);
        res.setMessage("保存成功");
        return res;
    }


    /**
     * @description 删除
     *
     * @author lss
     * @date 2024-01-15
     */
    @ApiOperation("删除")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "Authorization", value = "会话标识", dataType = "String", paramType = "header", required = true),
        @ApiImplicitParam(name = "ids", value = "删除id（支持批量删除）", dataTypeClass = Long.class , allowMultiple = true,paramType = "query", required = true),
    })
    @PreAuthorize("hasAnyAuthority('PurchaseContract_Remove','SaleContract_Remove','SUPER_ADMIN')")
    @ModuleLog("Contract")
    @PostMapping("contract_del")
        public JSONResult<Void> delEntity(HttpServletRequest request,Authentication authentication,@Size(min=1,max=50,message = "请选择要删除数据") Long[] ids) throws Exception{
        User user = ((UserAuthDetail)authentication.getPrincipal()).getUser();
        JSONResult<Void> res = new JSONResult<>();
        for(int i=0;i<ids.length;i++){
            Contract it = contractService.getById(ids[i]);
            contractService.removeById(it.getUuid());
        }
        request.setAttribute(LogConstant.LOG_KEY,new LogInfo(user.getId(), "删除，数据ID:" + StringUtils.join(ids)));
        res.setMessage("删除成功");
        res.setSuccess(true);
        return res;
    }

    @ApiOperation("审批 ")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "会话标识", dataType = "String", paramType = "header", required = true)
    })
    @PreAuthorize("hasAnyAuthority('PurchaseContract_Check','SaleContract_Check','SUPER_ADMIN')")
    @ModuleLog("Contract")
    @PostMapping("/contract_check")
    public JSONResult<Contract> saveDateCheck(HttpServletRequest request,Authentication authentication,ContractDto entity){
        User user = ((UserAuthDetail)authentication.getPrincipal()).getUser();
        JSONResult<Contract> res= contractBiz.saveCheck(user,entity);
        if(res.isSuccess()){
            request.setAttribute(LogConstant.LOG_KEY,new LogInfo(user.getId(), "审批，数据ID:"+res.firstData().getUuid()));
        }
        return res;
    }

    @ApiOperation("采销匹配")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "会话标识", dataType = "String", paramType = "header", required = true)
    })
    @PreAuthorize("hasAnyAuthority('PurchaseContract_Add','SaleContract_Add','SUPER_ADMIN')")
    @ModuleLog("Contract")
    @PostMapping("/purchase_sale_matching")
    public JSONResult<Contract> purchaseSaleMatching(HttpServletRequest request,Authentication authentication,ContractDto entity){
        User user = ((UserAuthDetail)authentication.getPrincipal()).getUser();
        JSONResult<Contract> res= contractBiz.purchaseSaleMatching(user,entity);
        if(res.isSuccess()){
            request.setAttribute(LogConstant.LOG_KEY,new LogInfo(user.getId(), "审批，数据ID:"+res.firstData().getUuid()));
        }
        return res;
    }


    @ApiOperation("查询合同重量")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "会话标识", dataType = "String", paramType = "header", required = true),
            @ApiImplicitParam(name = "ids", value = "合同id）", dataTypeClass = Long.class , allowMultiple = true,paramType = "query", required = true),
    })
    @ModuleLog("Contract")
    @PostMapping("/get_weight")
    public JSONResult<Contract> getWeight(HttpServletRequest request,Authentication authentication,Long[] ids){
        User user = ((UserAuthDetail)authentication.getPrincipal()).getUser();
       ContractDto contractDto = new ContractDto();
       contractDto.setUuids(ids);
        List<Contract> contracts = contractService.list(0, contractDto);
        for(Contract it :contracts){
            it.setTopContract(it.getMaterialTopName()+it.getIsContract());
            sumWeight(it);//计算合同量
        }
       Map<String,List<Contract>> contractMap = contracts.stream().collect(Collectors.groupingBy(Contract::getTopContract));
        List<Contract> cons = new ArrayList<>();
        for(String key:contractMap.keySet()){
            List<Contract> contractList = contractMap.get(key);
            Contract contract = contractList.get(0);
            for(int i=1;i<contractList.size();i++){
                Contract contract1 = contractList.get(i);
                contract.setContractQuantity(DecimalUtil.valueOf(contract1.getContractQuantity()).add(contract.getContractQuantity()).doubleValue());
                contract.setContractWeight(DecimalUtil.valueOf(contract1.getContractWeight()).add(contract.getContractWeight()).doubleValue());
            }
            cons.add(contract);
        }
        JSONResult<Contract> res = new JSONResult<>();
        res.setSuccess(true);
        res.setMessage("查询成功");
        res.setDatas(cons);
        return res;
    }

    //累计合同量、敞口
    public void sumWeight(Contract it){
        ContractDetailDto contractDetailDto = new ContractDetailDto();
        contractDetailDto.setContractUuid(it.getUuid());
        List<ContractDetail> contractDetails = contractDetailService.list(0, contractDetailDto);
        Double contractQuantity =0d;
        Double contractWeight = 0d;
        for(ContractDetail its:contractDetails){
            if(its.getWeight()!=null){
                contractQuantity  = contractQuantity+its.getWeight();
            }
            if(its.getSpotOpen()!=null){
                contractWeight = its.getSpotOpen()+contractWeight;
            }
        }
        it.setContractWeight(contractWeight);
        it.setContractQuantity(contractQuantity);
    }

}

